package com.gopay.bis.citic.fund.operation;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

/**
 * 国付宝发送中信测试类
 * @PayingServlet.java
 * @author dong-wang5@hnari.com
 * @2016年7月20日 上午10:02:15  www.gopay.com.cn Inc.All rights reserved.
 */
public class PayingServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	private static Logger logger = Logger.getLogger(PayingServlet.class);
	@SuppressWarnings("static-access")
	public void doPost(HttpServletRequest request,HttpServletResponse response)
	throws IOException,ServletException
	{ 
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/xml;charset=UTF-8");
		logger.info("客户端地址：" + request.getRequestURL());
		logger.info("服务器名称：" + request.getServerName());
		logger.info("服务器端口：" + request.getServerPort());
		logger.info("客户端IP ：" + request.getRemoteAddr());
		logger.info("客户端端口" + request.getRemotePort());
		logger.info("客户端名称" + request.getRemoteHost());
		Date req_date = new Date();
		StringMessage sm = new StringMessage();
		Map<String,String> map = sm.getReceivedMap(request);
//		InputStream is = request.getInputStream();
//		Map<String,String> map = sm.getReceived(is, null, null);
		logger.info("接收原始报文是:" + map);
		int ServerSocketPort = Integer.parseInt(Utils.getValueByName("bank_ServerSocketPort"));
		String ServerSocketIp = Utils.getValueByName("bank_ip");
        boolean isChecked = false;
        String errorCode = "ILLEGAL_SIGN";
        String errorMessage = "签名无效";
        String rep_msg="";   //返回支付宝报文
        String Real_Pack=""; //键值对格式报文主体
        
		try 
		{
			String sign = sm.getSign(map,"sign");
			logger.info("签名串是:" + sign);
			Real_Pack = sm.getRealMessage(map);
			logger.info("截取报文是:" + Real_Pack);
			isChecked = Utils.cartFundVerify(Real_Pack, sign);
			
		} 
		catch (Exception e) 
		{
			logger.info("验签时发生了异常!" + e);
			isChecked = false;
			errorCode = "ILLEGAL_SIGN";
			errorMessage = "不支持该签名类型!";
		}  
		logger.info("对业务报文的验签结果是:" + isChecked);
		if(isChecked)
		{
			Socket s = new Socket(ServerSocketIp,ServerSocketPort);
			s.setSoTimeout(60*1000);
			OutputStream out = s.getOutputStream();
			String xmlPack=""; 
			try 
			{
				xmlPack = Utils.PairzfbXML("C",Real_Pack,null,null);
//				xmlPack = CartoonUtil.addLenMsg2BusinessMsg(xmlPack, 20);
			} 
			catch (Exception e) 
			{
				logger.info(e);
			}
			StringBuffer zhifubaoReq  = new StringBuffer(xmlPack);
			out.write(zhifubaoReq.toString().getBytes("utf-8"));
			out.flush();
			InputStream in = s.getInputStream();
			byte[][] bank_res = streamToByteArr(in);
			logger.info("银行响应:"+new String(bank_res[0],"utf-8")+new String(bank_res[1],"utf-8"));
			//String [] tagNames={"service","deposit_time","errcode","error_msg","is_succ","serial_no"};
			InputStream reader = Utils.bytesToInputStream(bank_res[1]);
			List<String> list = sm.getNodeList(reader);
			String [] tagName = sm.getStringArrayByList(list);
			String msgPairStr = sm.XML2PairStr("S",Utils.bytesToInputStream(bank_res[1]), tagName, null, null, true);
			String msgpairbysigned = new String(msgPairStr);
			String signed = Utils.cartFundSignature(msgPairStr);
			msgpairbysigned = msgpairbysigned+"&sign="+signed+"&sign_type=RSA";
			logger.info("[" + new Date() + "]"+ "银行响应签名后的结果是:" + msgpairbysigned);
			OutputStream os = response.getOutputStream();
			os.write(msgpairbysigned.getBytes("utf-8"));
			reader.close();
			os.flush();
			in.close();
			out.close();
			s.close();
		}
		else
		{
			OutputStream os = response.getOutputStream();
			StringBuffer res = new StringBuffer();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
			String deposit_time = sdf.format(new Date());
			String errcode = errorCode;
			String error_msg = errorMessage;
			String  is_success = "F";
			String serial_no = sm.getValue(Real_Pack, "serial_no");
			
			res.append("deposit_time=" + deposit_time);
			res.append("&errcode=" + errcode);
			res.append("&error_msg=" + error_msg);
			res.append("&is_succ=" + is_success);
			res.append("&serial_no=" + serial_no);
		
			try {
				rep_msg = CipherStringBuilder.sortingMapToStr(Utils.PairStr2Map(res.toString(),null,null), null, null, true);
			} catch (Exception e) {
				logger.info(e);
			}
			
			String signed = Utils.cartFundSignature(rep_msg);
			//String signed = "signed";
			String signMsg = rep_msg+"&sign="+signed+"&sign_type=RSA";
			logger.info("失败时给中金支付的报文:"+signMsg);
			os.write(signMsg.getBytes("utf-8"));
			os.flush();
		}
		Date res_date = new Date();
		logger.info("单笔业务开始接收时间："+req_date+"--单笔业务结束时间："+res_date+"--业务处理时间是:"+(res_date.getTime()-req_date.getTime()));
	}
	public void doGet(HttpServletRequest request,HttpServletResponse response)
	throws IOException,ServletException
	{
		doPost(request,response);
	}
	public static byte[][] streamToByteArr(InputStream is)
    {
    	byte[][] returnByteArr = new byte[2][];
    	returnByteArr[0] = new byte[20];//报文特殊段
    	byte[] content = new byte[20];
    	byte[] returnBArr = null;//报文真实段
    	boolean flag = false;//标志流是否被截取，没有-false,被截取-true
    	long xmlLen = 0;//代表约定的报文长度
		int len = 0 ;		
		try {
			len =is.read(content);
			while(len != -1)
			{	
				if(len == 20)
				{
					if(flag == false)
					{
						byte[] tem = new byte[20];
						System.arraycopy(content, 0, tem, 0,20);
						xmlLen = Long.parseLong(new String(tem));
						flag = true;
						System.arraycopy(content, 0, returnByteArr[0] , 0, 20);
					}
					else
					{
						returnBArr = Utils.uniteTwoByteArr(returnBArr,content);		//当一个对象被奇怪的更改了，要检查有几个对象指向它，可能是因为它同时被多个引用所指向，被别的引用在什么地方操作			
					}
				}
				else
				{
					byte[] temp = new byte[len];
					System.arraycopy(content, 0, temp, 0, len);
					returnBArr = Utils.uniteTwoByteArr(returnBArr,temp);
				}	
				if(returnBArr!=null)
				{
					if(returnBArr.length>=xmlLen)
					{
						break;
					}
				}
				len = is.read(content);//程序可能阻塞在is.read(content))这里，一直读等待返回值,即直到遇见结束标志，但是此时流中若无结束标志，程序将被阻塞在这里
			}
		} catch (IOException e)
		{
			logger.info(e);
		}
		returnByteArr[1] = returnBArr;
		return returnByteArr;

    }
}
